from classfile.attribute_info import AttributeInfo, CODE, CONSTANT_VALUE, EXCEPTIONS, UN_PARSED, \
    RUNTIME_VISIBLE_ANNOTATIONS, RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTRIBUTE, ANNOTATION_DEFAULT


class MemberInfo:
    def __init__(self, constPool, accessFlags, nameIndex, descriptorIndex, attributes):
        self.constPool = constPool
        self.accessFlags = accessFlags
        self.nameIndex = nameIndex
        self.descriptorIndex = descriptorIndex
        self.attributes = attributes

    @property
    def name(self):
        return self.constPool.getUTF8(self.nameIndex)
    
    @property
    def descriptor(self):
        return self.constPool.getUTF8(self.descriptorIndex)

    @property
    def codeAttribute(self):
        for attr in self.attributes:
            if attr.type == CODE:
                return attr
        return None

    @property
    def constantValueAttribute(self):
        for attr in self.attributes:
            if attr == CONSTANT_VALUE:
                return attr
        return None

    @property
    def exceptionsAttribute(self):
        for attr in self.attributes:
            if attr == EXCEPTIONS:
                return attr
        return None

    @property
    def runtimeVisibleAnnotationsAttributeData(self):
        return self.getUnParsedAttributeData(RUNTIME_VISIBLE_ANNOTATIONS)

    @property
    def runtimeVisibleParameterAnnotationsAttributeData(self):
        return self.getUnParsedAttributeData(RUNTIME_VISIBLE_PARAMETER_ANNOTATIONS_ATTRIBUTE)

    @property
    def annotationDefaultAttributeData(self):
        return self.getUnParsedAttributeData(ANNOTATION_DEFAULT)

    def getUnParsedAttributeData(self, name):
        for attr in self.attributes:
            if attr.type == UN_PARSED and attr.name == name:
                return attr
        return None

    @staticmethod
    def readMembers(clsReader, constPool):
        count = int.from_bytes(clsReader.readU16(), "big")
        members = []
        for i in range(count):
            members.append(MemberInfo.readMember(clsReader, constPool))

    @staticmethod
    def readMember(clsReader, constPool):
        return MemberInfo(
            constPool,
            int.from_bytes(clsReader.readU16(), "big"),
            int.from_bytes(clsReader.readU16(), "big"),
            int.from_bytes(clsReader.readU16(), "big"),
            AttributeInfo.readAttributes(clsReader, constPool)
        )

